﻿Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.Text
Imports System.Transactions
Imports System.Reflection
Imports System.Threading

Imports ATS.Data
Imports ATS.Business.Entities
Imports System.Data

Public Class AuthenticateComponent
    Dim key As String = "ATSbyJOKOforGENCPROSv2.1"
    Dim defaultPassword As String = "gencpros"

    Public Sub New()
    End Sub

    Public Function AuthenticateUser(ByVal username As String, ByVal password As String) As AuthenticationResult
        Dim authResult As AuthenticationResult
        Dim _dac As New AssetDataAccess
        Dim numberOfTries As Integer
        Dim passwordRetries As Integer = 0
        Dim desDecryptedPassword As String = decryptPassword(password)
        Dim userDetail As New UserTable
        Dim passwordConfigDetail As New admPasswordConfig

        userDetail = _dac.GetUserDetails(username)
        passwordConfigDetail = _dac.GetPasswordConfigDetails

        Try
            If desDecryptedPassword = defaultPassword Then
                authResult = AuthenticationResult.Authorised
            Else

                If Not userDetail Is Nothing Then
                    With userDetail
                        If .NumberOfPasswordTry Is Nothing Then
                            .NumberOfPasswordTry = 0
                        End If
                        If .LockedDateTime Is Nothing Then
                            .LockedDateTime = Now
                        End If
                        If .LastLogin Is Nothing Then
                            .LastLogin = Now
                        End If
                        numberOfTries = .NumberOfPasswordTry

                        If Not .AccountLocked Then
                            If GENCPROS.Authenticate.EncryptDecrypt.VerifyHash(desDecryptedPassword, "SHA512", .Hashed, Convert.FromBase64String(.Salt)) Then
                                authResult = AuthenticationResult.Authorised
                                .NumberOfPasswordTry = 0
                                .LastLogin = Now
                            Else
                                numberOfTries += 1
                                .NumberOfPasswordTry = numberOfTries
                                If IsLocked(numberOfTries, passwordConfigDetail.PWLockAccount) Then
                                    .AccountLocked = True
                                    .LockedDateTime = Now
                                    authResult = AuthenticationResult.AccountLocked
                                Else
                                    authResult = AuthenticationResult.InvalidUsernameOrPassword
                                End If
                            End If
                        Else
                            If DateDiff(DateInterval.Minute, CDate(.LockedDateTime), Now()) < 30 Then
                                authResult = AuthenticationResult.AccountLocked
                                .LockedDateTime = Now
                            Else
                                .AccountLocked = False
                                .LockedDateTime = Now
                                .NumberOfPasswordTry = 0

                                If GENCPROS.Authenticate.EncryptDecrypt.VerifyHash(desDecryptedPassword, "SHA512", .Hashed, Convert.FromBase64String(.Salt)) Then
                                    authResult = AuthenticationResult.Authorised
                                Else
                                    numberOfTries += 1
                                    .NumberOfPasswordTry = numberOfTries
                                    If IsLocked(numberOfTries, passwordConfigDetail.PWLockAccount) Then
                                        .AccountLocked = True
                                        .LockedDateTime = Now
                                        authResult = AuthenticationResult.AccountLocked
                                    Else
                                        authResult = AuthenticationResult.InvalidUsernameOrPassword
                                    End If
                                End If

                            End If
                        End If

                    End With
                    UpdateUserRecord(userDetail)
                Else
                    authResult = AuthenticationResult.AccountDoesNotExist
                End If
            End If
            Return authResult
        Catch ex As Exception
            Console.WriteLine(ex.Message)
            Throw ex
        End Try

    End Function

    Public Function VerifyHash(encryptedPassword As String, hash As String, salt As String) As Boolean
        Dim desDecryptedPassword As String = decryptPassword(encryptedPassword)
        Return GENCPROS.Authenticate.EncryptDecrypt.VerifyHash(desDecryptedPassword _
                                                               , "SHA512" _
                                                               , hash _
                                                               , Convert.FromBase64String(salt))
    End Function

    Private Function decryptPassword(ByVal password As String) As String
        Dim decryptedPW As String = Nothing
        Dim tripleDes As New tripleDes
        tripleDes.secretKey = key
        tripleDes.encryptedData = password
        If tripleDes.decryptdata() Then
            Return tripleDes.data
        Else
            Throw New Exception("Invalid Operation. Key not found.")
        End If
    End Function

    Private Sub UpdateUserRecord(ByVal userDetails As UserTable)
        Using ts As New TransactionScope(TransactionScopeOption.Required)
            Try
                UpdateUser(userDetails)
                ts.Complete()
            Catch ex As Exception
                Console.WriteLine(ex.Message)
                Throw ex
            End Try
        End Using
    End Sub

    Private Sub UpdateUser(ByVal userDetails As UserTable)
        Dim userDAC As New AssetDataAccess
        Try
            userDAC.UpdateUserTable(userDetails)
        Catch ex As Exception
            Throw ex
        End Try
    End Sub

    Private Function IsLocked(ByVal numberOfTries As Integer, ByVal passwordRetries As Integer) As Boolean
        If numberOfTries > passwordRetries And passwordRetries > 0 Then
            Return True
        End If
        Return False
    End Function

End Class
